package io.renren.modules.workmanagement.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.Query;
import io.renren.modules.workmanagement.constans.UserConstans;
import io.renren.modules.workmanagement.dao.QuestionBankDao;
import io.renren.modules.workmanagement.entity.CourseEntity;
import io.renren.modules.workmanagement.entity.QuRepoEntity;
import io.renren.modules.workmanagement.entity.QuestionBankCourseRelEntity;
import io.renren.modules.workmanagement.entity.QuestionBankEntity;
import io.renren.modules.workmanagement.service.*;
import io.renren.modules.workmanagement.utils.PojoUtils;
import io.renren.modules.workmanagement.vo.QuestionBankReturnVO;
import io.renren.modules.workmanagement.vo.QuestionBankVO;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;


@Service("questionBankService")
public class QuestionBankServiceImpl extends ServiceImpl<QuestionBankDao, QuestionBankEntity> implements QuestionBankService {
    @Autowired
    private QuestionBankCourseRelService questionBankCourseRelService;
    @Autowired
    private CourseService courseService;
    @Autowired
    private QuRepoService quRepoService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        Long userId = (Long) params.get(UserConstans.USER_ID_KEY);
        LambdaQueryWrapper<QuestionBankEntity> wrapper = new LambdaQueryWrapper<>();
        String key = (String) params.get("key");
        if(StringUtils.isNotBlank(key)){
            wrapper.like(QuestionBankEntity::getTitle,"%"+key+"%");
            List<CourseEntity> courseEntityList = courseService.likeByName(key);
            if(CollectionUtils.isNotEmpty(courseEntityList)){
                List<Long> courseIds = PojoUtils.streamMapList(courseEntityList, CourseEntity::getId);
                List<QuestionBankCourseRelEntity> questionBankCourseRelEntities = questionBankCourseRelService.listByCourseIds(courseIds);
                List<Long> bankIds = PojoUtils.streamMapList(questionBankCourseRelEntities, QuestionBankCourseRelEntity::getBankId);
                wrapper.or().in(QuestionBankEntity::getId,bankIds);
            }
        }
        IPage<QuestionBankEntity> page = this.page(
                new Query<QuestionBankEntity>().getPage(params),
                wrapper.eq(QuestionBankEntity::getCreateUser, userId)
        );
        List<QuestionBankEntity> bankEntityList = page.getRecords();
        List<Long> bankIds = PojoUtils.streamMapList(bankEntityList, QuestionBankEntity::getId);
        List<QuestionBankCourseRelEntity> courseRelEntityList = questionBankCourseRelService.listByBankIds(bankIds);
        Map<Long, Long> bankCourseIdMap = PojoUtils.listToMap(courseRelEntityList, QuestionBankCourseRelEntity::getBankId, QuestionBankCourseRelEntity::getCourseId);
        List<Long> courseIds = PojoUtils.streamMapList(courseRelEntityList, QuestionBankCourseRelEntity::getCourseId);
        List<CourseEntity> courseEntityList = courseService.listByIds(courseIds);
        Map<Long, CourseEntity> courseEntityMap = PojoUtils.listToMap(courseEntityList, CourseEntity::getId, Function.identity());
        IPage<QuestionBankReturnVO> convert = page.convert(item -> {
            Long courseId = bankCourseIdMap.get(item.getId());
            CourseEntity courseEntity = courseEntityMap.get(courseId);
            QuestionBankReturnVO questionBankReturnVO = new QuestionBankReturnVO();
            BeanUtils.copyProperties(item, questionBankReturnVO);
            questionBankReturnVO.setCourseId(courseId);
            questionBankReturnVO.setCourseName(courseEntity.getName());
            return questionBankReturnVO;
        });
        return new PageUtils(convert);
    }

    @Override
    public List<QuestionBankEntity> getListByClassCourseIdAndCreateUser(Long courseId, Long userId) {
        LambdaQueryChainWrapper<QuestionBankEntity> wrapper = this.lambdaQuery();
        wrapper.eq(QuestionBankEntity::getCreateUser, userId);
        if (courseId != null) {
            List<QuestionBankCourseRelEntity> questionBankCourseRelEntities = questionBankCourseRelService.listByCourseId(courseId);
            List<Long> bankIds = PojoUtils.streamMapList(questionBankCourseRelEntities, QuestionBankCourseRelEntity::getBankId);
            List<Long> hasQuestionBankIds = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(bankIds)) {
                List<QuRepoEntity> quRepoEntities = quRepoService.listByBankIds(bankIds);
                Map<Long, List<QuRepoEntity>> listMap = PojoUtils.listGroupByKey(quRepoEntities, QuRepoEntity::getRepoId);
                listMap.forEach((k, v) -> {
                    if (v.size() > 0) {
                        hasQuestionBankIds.add(k);
                    }
                });
            }
            if(CollectionUtils.isNotEmpty(hasQuestionBankIds)){
                wrapper.in(QuestionBankEntity::getId, hasQuestionBankIds);
                return wrapper.list();
            }else{
                return new ArrayList<>(0);
            }
        } else {
            return wrapper.list();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveQuestionBank(QuestionBankVO questionBank, Long userId) {
        //保存题库
        QuestionBankEntity entity = new QuestionBankEntity();
        entity.setCreateUser(userId);
        entity.setTitle(questionBank.getTitle());
        entity.setRemark(questionBank.getRemark());
        this.save(entity);
        //保存题库课程关联
        QuestionBankCourseRelEntity questionBankCourseRelEntity = new QuestionBankCourseRelEntity();
        questionBankCourseRelEntity.setBankId(entity.getId());
        questionBankCourseRelEntity.setCourseId(questionBank.getCourseId());
        questionBankCourseRelService.save(questionBankCourseRelEntity);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateQuestionBank(QuestionBankVO questionBank) {
        QuestionBankEntity entity = new QuestionBankEntity();
        entity.setId(questionBank.getId());
        entity.setTitle(questionBank.getTitle());
        entity.setRemark(questionBank.getRemark());
        this.updateById(entity);
        QuestionBankCourseRelEntity questionBankCourseRelEntity = questionBankCourseRelService.getByBankId(questionBank.getId());
        if (!questionBankCourseRelEntity.getCourseId().equals(questionBank.getCourseId())) {
            //删除题库课程关联
            questionBankCourseRelService.removeById(questionBankCourseRelEntity);
            //保存题库与课程的新关联
            questionBankCourseRelEntity = new QuestionBankCourseRelEntity();
            questionBankCourseRelEntity.setBankId(questionBank.getId());
            questionBankCourseRelEntity.setCourseId(questionBank.getCourseId());
            questionBankCourseRelService.save(questionBankCourseRelEntity);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeQuestionBanks(List<String> bankIds) {
        //删除题库
        this.removeByIds(bankIds);
        //删除题库课程关联
        questionBankCourseRelService.removeByBankIds(bankIds);
    }

    @Override
    public QuestionBankVO getByBankId(Long id) {
        QuestionBankEntity questionBank = this.lambdaQuery().eq(QuestionBankEntity::getId, id).one();
        //查询题库相关联的课程Id
        QuestionBankCourseRelEntity bankCourseRelEntity = questionBankCourseRelService.getByBankId(questionBank.getId());
        QuestionBankVO questionBankVO = new QuestionBankVO();
        questionBankVO.setId(id);
        questionBankVO.setCourseId(bankCourseRelEntity.getCourseId());
        questionBankVO.setTitle(questionBank.getTitle());
        questionBankVO.setRemark(questionBank.getRemark());
        return questionBankVO;
    }

    @Override
    public List<QuestionBankEntity> likeByName(String key) {
        return this.lambdaQuery().like(QuestionBankEntity::getTitle, key).list();
    }

}
